extends NodeState


@export var enemy: BasicEnemy

var velocity: Vector2 = Vector2.ZERO
var height: float = 0.0
var height_speed: float = 0.0

var is_falling: bool = false


func _ready():
	await get_tree().process_frame
	enemy.collateralDamageEmitter.area_entered.connect(on_emit_collateral_damage)
	enemy.collateralDamageEmitter.body_entered.connect(on_wall_hit)


func _on_process(delta : float) -> void:
	enemy.position += velocity * delta
	if is_falling:
		process_fall(delta)


func _on_physics_process(_delta : float) -> void:
	pass


func _on_next_transitions() -> void:
	pass


func _on_enter() -> void:
	height = 0.0
	is_falling = false
	enemy.collisionShape.set_deferred("disabled", true)
	enemy.collateralDamageEmitter.set_deferred("monitoring", true)
	enemy.damageReceiver.set_deferred("monitorable", false)

	enemy.look_at_player()
	process_animation()
	process_affected()


func _on_exit() -> void:
	enemy.collisionShape.set_deferred("disabled", false)
	enemy.collateralDamageEmitter.set_deferred("monitoring", false)


func process_animation():
	enemy.animationPlayer.play(BasicEnemy.ANIMATION_FLY)


# 受到攻击时的效果
func process_affected():
	var emit_direction := enemy.take_damage_emit_direction()
	if emit_direction == null:
		return
	var direction: Vector2 = Vector2.RIGHT if emit_direction.x > 0 else Vector2.LEFT
	velocity = direction * enemy.flight_speed


func change_to_fall(target: Node2D):
	SoundPlayer.play(SoundManager.Sound.HIT2)

	var direction: Vector2 = Vector2.RIGHT if target.global_position.x < enemy.global_position.x else Vector2.LEFT
	velocity = direction * enemy.knockback_intensity
	height_speed = enemy.knockdown_intensity

	enemy.look_at_node(target)
	enemy.animationPlayer.play(BasicEnemy.ANIMATION_FALL)
	is_falling = true


func process_fall(delta: float):
	enemy.characterSprite.position = Vector2.UP * height

	height += height_speed * delta
	# 高度降为0时进入倒地状态
	if height < 0.0:
		height = 0.0
		velocity = Vector2.ZERO
		transition_state(BasicEnemy.STATE_GROUNDED)
	else:
		height_speed -= enemy.gravity * delta


# 与其他敌人发生碰撞
func on_emit_collateral_damage(receiver_area: Area2D):
	if enemy.stateMachine.current_node_state_name != BasicEnemy.STATE_FLY:
		return
	var damage_receiver: DamageReceiver = receiver_area as DamageReceiver
	if damage_receiver == null:
		return
	# 可能触发自己的伤害接收组件，故在此判断
	if enemy.damageReceiver == damage_receiver:
		return

	damage_receiver.damage_received.emit(0,
										receiver_area.global_position - enemy.collateralDamageEmitter.global_position,
										DamageReceiver.HitType.KNOCK_DOWN)
	change_to_fall(receiver_area)


# 与墙发生碰撞
func on_wall_hit(body: Node2D):
	if enemy.stateMachine.current_node_state_name != BasicEnemy.STATE_FLY:
		return
	var wall = body as AnimatableBody2D
	if wall == null:
		return
	change_to_fall(wall)
